﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace SafeLoad.NControl.Assist
{
	public class NCurveLine
	{
		public delegate Point CalcLinePoint(DateTime time, double value);
		public delegate Point CalcAlarmInfoPoint(DateTime time, double value, int fontSize);

		public NCurveLine(Canvas curve,  string lineName, Color lineColor)
		{
			this.curveCanvas = curve;
			this.LineName = lineName;
			this.LineColor = lineColor;
			this.LineThickness = 2d;
			this.dataList = new List<NCurvePoint>();
			this.lastLine = null;
			this.AlarmFontSize = 12;
		}

		private List<NCurvePoint> dataList;
		private Canvas curveCanvas;
		/// <summary>
		/// 最后一条线
		/// </summary>
		private Polyline lastLine;

		/// <summary>
		/// 根据时间和值来计算点
		/// </summary>
		public CalcLinePoint CalcPointFunc { get; set; }
		/// <summary>
		/// 根据时间和值来计算报警信息点
		/// </summary>
		public CalcAlarmInfoPoint CalcAlarmInfoFunc { get; set; }

		public void LeftShift(DateTime minTime)
		{
			int removeCount = dataList.Where(p => p.Time < minTime).Count();
			if (removeCount > 0)
			{
				dataList.RemoveRange(0, removeCount);
			}
			this.lastLine = null;
		}

		/// <summary>
		/// 添加一个数据点
		/// </summary>
		/// <param name="time">时间</param>
		/// <param name="value">数据值</param>
		/// <param name="alarm">是否报警</param>
		public void AddData(DateTime time, double value, bool alarm = false)
		{
			NCurvePoint newPoint = new NCurvePoint(time, value, alarm);
			NCurvePoint lastPoint = null;
			if (dataList.Count() > 0)
			{
				lastPoint = dataList.Last();
				if (lastPoint.Time >= time)
				{
					return;
				}
			}

			Point point = CalcPointFunc(time, value);
			if (lastLine != null)
			{
				lastLine.Points.Add(point);
				if (lastPoint != null && lastPoint.IsAlarm != alarm)
				{
					DrawNewLine(newPoint);
				}
			}
			else
			{
				//添加一个新的折线
				DrawNewLine(newPoint);
			}

			dataList.Add(newPoint);
		}

		/// <summary>
		/// 重绘折线图
		/// </summary>
		public void Repaint()
		{
			if (dataList.Count == 0)
				return;

			bool alarmFlag = false;
			lastLine = null;

			foreach(NCurvePoint point in dataList)
			{
				Point linePoint = CalcPointFunc(point.Time, point.Data);

				if (lastLine == null || alarmFlag != point.IsAlarm)
				{
					if (lastLine != null)
					{
						lastLine.Points.Add(linePoint);
					}

					alarmFlag = point.IsAlarm;
					DrawNewLine(point);
				}

				lastLine.Points.Add(linePoint);
			}
		}


		private void DrawNewLine(NCurvePoint point)
		{
			Point linePoint = CalcPointFunc(point.Time, point.Data);
			lastLine = new Polyline();
			lastLine.StrokeThickness = LineThickness;
			lastLine.Stroke = new SolidColorBrush(point.IsAlarm ? AlarmColor : LineColor);
			lastLine.Points.Add(linePoint);
			curveCanvas.Children.Add(lastLine);

			if (point.IsAlarm)
			{
				//需要输出报警点
				Ellipse alarmEllipse = new Ellipse();
				alarmEllipse.Width = LineThickness * 3;
				alarmEllipse.Height = LineThickness * 3;
				alarmEllipse.Fill = new SolidColorBrush(AlarmColor);
				curveCanvas.Children.Add(alarmEllipse);
				Canvas.SetLeft(alarmEllipse, linePoint.X - alarmEllipse.Width / 2);
				Canvas.SetTop(alarmEllipse, linePoint.Y - alarmEllipse.Height / 2);

				//输出报警信息
				if (!string.IsNullOrEmpty(AlarmInfo))
				{
					Point infoPoint = CalcAlarmInfoFunc(point.Time, point.Data, AlarmFontSize);
					WpfUtils.DrawString(curveCanvas, AlarmInfo, AlarmColor, infoPoint.X, infoPoint.Y,
						100, 30, HorizontalAlignment.Left, VerticalAlignment.Center);
				}
			}
		}


		/// <summary>
		/// 曲线名称
		/// </summary>
		public string LineName { get; set; }

		/// <summary>
		/// 线条的宽度
		/// </summary>
		public double LineThickness { get; set; }

		/// <summary>
		/// 曲线颜色
		/// </summary>
		public Color LineColor { get; set; }

		/// <summary>
		/// 报警颜色
		/// </summary>
		public Color AlarmColor { get; set; }

		public string AlarmInfo { get; set; }

		public int AlarmFontSize { get; set; }
	}
}
